package caser.cairngorm.services.async
{
	import com.adobe.cairngorm.commands.ICommand;
	import com.adobe.cairngorm.control.CairngormEvent;
	
	import flash.events.Event;
	
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.soap.WebService;

	public class ServiceMethodCallCommand implements ICommand
	{
		private static var requestContainer: RequestContainer = new RequestContainer();
		
		
		private static function addEventListeners(service: Object, onResultHandler: Function, onFaultHandler: Function): void
		{
			service.addEventListener(ResultEvent.RESULT, onResultHandler);
			service.addEventListener(FaultEvent.FAULT, onFaultHandler);
		}
		private static function removeEventListeners(service: Object, onResultHandler: Function, onFaultHandler: Function): void
		{
			service.removeEventListener(ResultEvent.RESULT, onResultHandler);
			service.removeEventListener(FaultEvent.FAULT, onFaultHandler);
		}
		
		
		
		
		public function ServiceMethodCallCommand()
		{
			super();
		}
		public virtual function execute(event: CairngormEvent): void 
		{  
			var 
				serviceMethodCallEvent: ServiceMethodCallEvent = event as ServiceMethodCallEvent;
			
			var 
				requestContainerItem: RequestContainerItem = new RequestContainerItem(
					null,
					event,
					serviceMethodCallEvent.callBacksCollection,
					serviceMethodCallEvent.serviceMethodCallContainer
				);
			
			if (!serviceMethodCallEvent.serviceMethodCallContainer.beforeExecute(event))
			{
				callbacksExecute(event, requestContainerItem);
				return;
			}//if
				
			addEventListeners(	
				 serviceMethodCallEvent.serviceMethodCallContainer.getService(),
				 onResultHandler,
				 onFaultHandler
			);
				 
			/*
			var 
				service: Object = serviceMethodCallEvent.serviceMethodCallContainer.getService();
				service.addEventListener(ResultEvent.RESULT, onResultHandler);
				service.addEventListener(FaultEvent.FAULT, onFaultHandler);
			*/

			requestContainerItem.asyncToken = 
				serviceMethodCallEvent.
					serviceMethodCallContainer.
						callServiceMethod(event);
									
			requestContainer.addItem(requestContainerItem);

			serviceMethodCallEvent.serviceMethodCallContainer.afterExecute(event);
		}
		public virtual function onResultHandler(event: ResultEvent): void
		{
			var 
				reqeustContainerItem: RequestContainerItem = requestContainer.findRequestByAsyncToken(event.token);
			
			if (reqeustContainerItem != null)
			{
				var 
					requestContainerItem: RequestContainerItem = requestContainer.removeRequestByAsyncToken(event.token);
				
				removeEventListeners(		
					(requestContainerItem.event as ServiceMethodCallEvent).serviceMethodCallContainer.getService(),
					onResultHandler,
					onFaultHandler
				);
				
				var
					serviceMethodCallContainer: IServiceMethodCallContainer = requestContainerItem.dataObject as IServiceMethodCallContainer;
					serviceMethodCallContainer.resultHandler(requestContainerItem.event, event);
					serviceMethodCallContainer.afterResponse(requestContainerItem.event, event);

				callbacksExecute(event, requestContainerItem);
			}//if
		}
		public virtual function onFaultHandler(event: FaultEvent): void
		{
			var 
				reqeustContainerItem: RequestContainerItem = requestContainer.findRequestByAsyncToken(event.token);

			if (reqeustContainerItem != null)
			{
				var 
					requestContainerItem: RequestContainerItem = requestContainer.removeRequestByAsyncToken(event.token);

				removeEventListeners(		
					(requestContainerItem.event as ServiceMethodCallEvent).serviceMethodCallContainer.getService(),
					onResultHandler,
					onFaultHandler
				);

				var 
					serviceMethodCallContainer: IServiceMethodCallContainer = requestContainerItem.dataObject as IServiceMethodCallContainer;
					serviceMethodCallContainer.faultHandler(requestContainerItem.event, event);
					serviceMethodCallContainer.afterResponse(requestContainerItem.event, event);

				callbacksExecute(event, requestContainerItem);
			}//if
		}
		private function callbacksExecute(event: Event, requestContainerItem: RequestContainerItem): void
		{
			for each (var callBack: Function in requestContainerItem.callBacksCollection)
			{
				if (callBack != null)
					callBack.call(null, requestContainerItem.event, event);
			}// foreach
		}
		
	}
}